<?php

namespace App\Http\Controllers\API;

use App\Http\Requests\API\CreateStaffOrderAPIRequest;
use App\Http\Requests\API\UpdateStaffOrderAPIRequest;
use App\Models\StaffOrder;
use App\Models\StaffInfo;
use App\Models\StaffCard;
use App\Repositories\StaffOrderRepository;
use App\Repositories\CarAuthRepository;
use App\Repositories\CarAuthLogRepository;

use App\Services\AuthServices;

use App\Http\Controllers\AppBaseController;
use App\Criteria\StaffOrderSearchCriteria;
use App\Criteria\StaffOrderByUidCriteria;

use Illuminate\Http\Request;
use InfyOm\Generator\Criteria\LimitOffsetCriteria;
use Prettus\Repository\Criteria\RequestCriteria;
use Response;
use Illuminate\Support\Facades\Log;


/**
 * Class StaffOrderController
 * @package App\Http\Controllers\API
 */

class StaffOrderAPIController extends AppBaseController
{
    use AuthServices;

    /** @var  StaffOrderRepository */
    private $staffOrderRepository;

    public function __construct(
                        StaffOrderRepository $staffOrderRepo,
                        CarAuthRepository $carAuthRepo,
                        CarAuthLogRepository $carAuthLogRepo) {
        $this->staffOrderRepository = $staffOrderRepo;
        $this->carAuthRepository = $carAuthRepo;
        $this->carAuthLogRepository = $carAuthLogRepo;
    }

    /**
     * Display a listing of the StaffOrder.
     * GET|HEAD /staffOrders
     *
     * @param Request $request
     * @return Response
     */
    public function index(Request $request)
    {
        $this->staffOrderRepository->pushCriteria(new RequestCriteria($request));
        $this->staffOrderRepository->pushCriteria(new LimitOffsetCriteria($request));
        $this->staffOrderRepository->pushCriteria(new StaffOrderSearchCriteria);
        // $staffOrders = $this->staffOrderRepository->all();
        $staffOrders = $this->staffOrderRepository->paginate($request->limit);

        return $this->sendResponse($staffOrders->toArray(), 'Staff Orders retrieved successfully');
    }

    /**
     * Display a listing of the StaffOrder.
     * GET|HEAD /staffOrders
     *
     * @param Request $request
     * @return Response
     */
    public function listByUid(Request $request)
    {
        $uid = $request->input('uid');
        if (empty($uid)) {
            return $this->sendError('invalid uid');
        }
        $this->staffOrderRepository->pushCriteria(new RequestCriteria($request));
        $this->staffOrderRepository->pushCriteria(new LimitOffsetCriteria($request));
        $this->staffOrderRepository->pushCriteria(new StaffOrderByUidCriteria);
        // $staffOrders = $this->staffOrderRepository->all();
        $staffOrders = $this->staffOrderRepository->paginate($request->limit);

        return $this->sendResponse($staffOrders->toArray(), 'Staff Orders retrieved successfully');
    }

    // 生成订单号
    private function _generateSN($uid)
    {
        return sprintf(
                    '%s%s%s', 
                    time(), 
                    $uid,
                    strtoupper(str_random(8))
                );
    }

    /**
     * Store a newly created StaffOrder in storage.
     * POST /staffOrders
     *
     * @param CreateStaffOrderAPIRequest $request
     *
     * @return Response
     */
    public function store(CreateStaffOrderAPIRequest $request)
    {
        $input = $request->all();
        $uid   = $input['uid'];

        if (empty($uid)) {
            return $this->sendError('Invalid uid');
        }

        $card_type = $input['card_type'];
        $card_id   = $input['card_id'];

        $staffInfo = StaffInfo::where('id', $uid)->first();
        if (empty($staffInfo)) {
            return $this->sendError('Staff Info not found');
        }

        unset($input['uid']);
        $input['staff_id']   = $uid;
        $input['order_no']   = $this->_generateSN($uid);
        $input['staff_name'] = $staffInfo->name;
        $input['vpl_number'] = $staffInfo->vpl_number;
        $input['oid']    = $staffInfo->oid;
        $input['id_no']  = $staffInfo->idno;
        $input['mobile'] = $staffInfo->mobile;

        if ($card_type == 1) {
            $card = StaffCard::where('id', $card_id)->first();
            if (empty($card)) {
                return $this->sendError('Invalid Card ID');
            }

            $input['card_name'] = $card->name;
            $input['valid_time_start'] = $card->valid_time_start;
            $input['valid_time_end']   = $card->valid_time_end;
        } else {
            $input['card_name'] = sprintf('%s-月卡', $input['card_date']);
            $input['valid_time_start'] = mktime(
                                            0, 0, 0, 
                                            intval(substr($input['card_date'], -2)), 
                                            1, 
                                            substr($input['card_date'], 0, 4)
                                        );
            $input['valid_time_end'] = mktime(
                                            23, 59, 59, 
                                            intval(substr($input['card_date'], -2))+1, 
                                            0, 
                                            substr($input['card_date'], 0, 4) 
                                        );
    }



        $input['status'] = 0;

        $staffOrders = $this->staffOrderRepository->create($input);

        return $this->sendResponse($staffOrders->toArray(), 'Staff Order saved successfully');
    }

    /**
     * Display the specified StaffOrder.
     * GET|HEAD /staffOrders/{id}
     *
     * @param  int $id
     *
     * @return Response
     */
    public function show($id)
    {
        /** @var StaffOrder $staffOrder */
        $staffOrder = $this->staffOrderRepository->findWithoutFail($id);

        if (empty($staffOrder)) {
            return $this->sendError('Staff Order not found');
        }

        return $this->sendResponse($staffOrder->toArray(), 'Staff Order retrieved successfully');
    }

    /**
     * Update the specified StaffOrder in storage.
     * PUT/PATCH /staffOrders/{id}
     *
     * @param  int $id
     * @param UpdateStaffOrderAPIRequest $request
     *
     * @return Response
     */
    public function update($id, UpdateStaffOrderAPIRequest $request)
    {
        $input = $request->all();

        /** @var StaffOrder $staffOrder */
        $staffOrder = $this->staffOrderRepository->findWithoutFail($id);

        if (empty($staffOrder)) {
            return $this->sendError('Staff Order not found');
        }

        $staffOrder = $this->staffOrderRepository->update($input, $id);

        return $this->sendResponse($staffOrder->toArray(), 'StaffOrder updated successfully');
    }

    /**
     * Remove the specified StaffOrder from storage.
     * DELETE /staffOrders/{id}
     *
     * @param  int $id
     *
     * @return Response
     */
    public function destroy($id)
    {
        /** @var StaffOrder $staffOrder */
        $staffOrder = $this->staffOrderRepository->findWithoutFail($id);

        if (empty($staffOrder)) {
            return $this->sendError('Staff Order not found');
        }

        $staffOrder->delete();

        return $this->sendResponse($id, 'Staff Order deleted successfully');
    }

    /**
     * Update the specified StaffOrder in storage.
     * PUT/PATCH /staff/order/payment/callback
     *
     * @param  int $id
     * @param UpdateStaffOrderAPIRequest $request
     *
     * @return Response
     */
    public function callback(Request $request)
    {
        // post param
        $input = $request->input();

        if (!isset($input['sign'])) {
            return $this->sendError('回调签名认证失败！');
        }

        if (!isset($input['orderNumber']) || !isset($input['orderAmount'])) {
            return $this->sendError('订单号或订单金额不正确！');
        }

        $inputSign = $input['sign'];

        unset($input['sign']);

        // sort array by key
        asort($input);

        $hashSK = md5(config('custom.wechat_miniapp_sk'));

        $input = $request->all();

        $this->log(sprintf('CALLBACK: %s%s', json_encode($input), PHP_EOL));

        // 订单号
        $order_no     = $input['orderNumber'];
        $order_amount = $input['orderAmount'];

        $staffOrder = StaffOrder::where('order_no', $order_no)->first();

        if (empty( $staffOrder )) {
            return $this->sendError(sprintf('未找到订单：%s。', $order_no));
        }

        // 已支付
        if ($staffOrder->status == 1) {
            return $this->sendError(sprintf('订单：%s 已支付成功。', $order_no));
        }

        // 更新订单状态
        $this->staffOrderRepository->update(['status' => 1], $staffOrder->id);
        // 下发授权
        $this->_issueAuth($staffOrder);

        return $this->sendResponse($staffOrder->order_no, 'StaffOrder updated successfully');
    }


    // 下发授权
    private function _issueAuth($staffOrder)
    {
        // staff authed parks
        $parks = config('custom.staff_auth_parks');
        $vpl_number = $staffOrder->vpl_number;
        $input = [
            'type'        => config('custom.staff_auth_type'),
            'share_count' => config('custom.staff_share_count'),
            'share'       => config('custom.staff_share_count') > 0 ? 1: 0,
            'mobile'      => $staffOrder->mobile,
            'validbtime'  => date('Y-m-d H:i:s', $staffOrder->valid_time_start),
            'validetime'  => date('Y-m-d H:i:s', $staffOrder->valid_time_end),
            'vpl_number'  => $staffOrder->vpl_number,

            'username'    => $staffOrder->staff_name,
            'email'       => '',
            'operator_id' => 0,
            'operator'    => '员工车接口',
            'priority'    => 2,
            'images'      => '',
        ];


        foreach ($parks as $park) {
            $data = $input;

            // 同一车场 车辆 一个时间段里只有一次
            $carAuths = $this->carAuthRepository->findWhere([
                'park_code' => $park,
                ['vpl_number', 'like', '%'.$vpl_number.'%' ],
                ['validbtime', '<=', $data['validbtime']],
                ['validetime', '>=', $data['validbtime']]
            ])->all(["id"]);

            if(obj2arr($carAuths)){
                $this->log('已存在的此车辆授权时间段有重叠');
                continue;
            }
            $carAuths = $this->carAuthRepository->findWhere([
                'park_code' => $park,
                ['vpl_number', 'like', '%'.$vpl_number.'%' ],
                ['validbtime', '<=', $data['validetime']],
                ['validetime', '>=', $data['validetime']]
            ])->all(["id"]);

            if(obj2arr($carAuths)){
                $this->log('已存在的此车辆授权时间段有重叠');
                continue;
            }

            $data['park_code'] = $park;
            $data['cardno']    = sprintf('%sNO%s', $staffOrder->order_no, $park);
            $data['serial_no'] = sprintf('%sSN%s', $staffOrder->order_no, $park);
            $data['option']    = 'add';

            $carAuths = $this->carAuthLogRepository->create($data);

            $data['validbtime'] = strtotime($data['validbtime']);
            $data['validetime'] = strtotime($data['validetime']);

            if($carAuths) {
                $data['vpl_number'] = sprintf('[["%s",""]]', $vpl_number);

                // 查看返回状态
                $this->log('开始传递 CAR data');
                $this->log('参数数据:'.json_encode($data));
                $res = $this->sendAuthData($data);
                $this->log('返回参数：'.json_encode($res));
                if($res['code'] == 0) {
                    $this->carAuthLogRepository->update(['issued_status' => 1], $carAuths->id);
                } else {
                    $this->carAuthLogRepository->update(['issued_status' => 2], $carAuths->id);
                }
            }
        }
        $this->log('正在下发授权中......');
        return true;
    }

}
